﻿using mozhi.smarterp.Business.Enums;
using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;

namespace mozhi.smarterp.Business.Sales
{
    /// <summary>
    /// 销售订单
    /// </summary>
    public class SaleOrder : DocumentAggregateRoot<SaleOrderItem>
    {
        public Guid CustomerId { get; private set; }

        public Customer Customer { get; private set; }

        public string Address { get; private set; }

        /// <summary>
        /// 销售员
        /// </summary>
        public Guid? SalePersonId { get; private set; }

        public Employee SalePerson { get; private set; }

        public Guid? PaymentTermId { get; private set; }

        public SaleOrderType Type { get; private set; }

        public List<SaleOrderAdvanceReceiptItem> AdvanceReceiptItems { get; private set; }

        private SaleOrder() { }

        public SaleOrder(Guid id, string number, DateTime date, bool includeTax, Customer customer, string address, Currency currency, Department department, Employee salePerson,
            string comment, Guid? paymentTermId, SaleOrderType type) : base(id, number, date, includeTax, currency, currency.ExchangeRate, department, comment)
        {

            Customer = customer;
            CustomerId = Customer == null ? default : Customer.Id;

            Address = address;

            Department = department;
            DepartmentId = department?.Id;

            SalePerson = salePerson;
            SalePersonId = salePerson?.Id;

            PaymentTermId = paymentTermId;

            Currency = currency;
            CurrencyId = currency == null ? default : currency.Id;
            ExchangeRate = currency == null ? 0 : currency.ExchangeRate;

            Type = type;

            Date = date;
            IncludeTax = includeTax;

            Comment = comment;

            Validate();
        }

        public void Change(DateTime date, bool includeTax , Customer customer, string address, Currency currency , Department department , Employee salePerson, Guid? paymentTermId, SaleOrderType type , string comment)
        {
            Customer = customer;
            CustomerId = Customer == null ? default : Customer.Id;

            Address = address;

            Department = department;
            DepartmentId = department?.Id;

            SalePerson = salePerson;
            SalePersonId = salePerson?.Id;

            PaymentTermId = paymentTermId;

            Currency = currency;
            CurrencyId = currency==null ? default : currency.Id;
            ExchangeRate = currency == null ? 0 : currency.ExchangeRate;

            Type = type;

            Date = date;
            IncludeTax = includeTax;

            Comment = comment;

            Validate();
        }

        public void SetAdvanceReceiptItems(List<SaleOrderAdvanceReceiptItem> items)
        {
            if (Status != DocumentStatusType.Approved && items.Any(x => x.AdvanceCollectId.HasValue))
                throw new UserFriendlyException("未审核的销售订单不允许关联预付款单", "100000");

            AdvanceReceiptItems = AdvanceReceiptItems ?? new List<SaleOrderAdvanceReceiptItem>();

            if (items.IsNullOrEmpty())
                AdvanceReceiptItems.Clear();

            AdvanceReceiptItems = AdvanceReceiptItems ?? new List<SaleOrderAdvanceReceiptItem>();

            foreach (var item in items)
            {
                var match = AdvanceReceiptItems.FirstOrDefault(x => x.Id == item.Id);

                if (match == null)
                {
                    item.CalculateAmount(TotalAmountFr, ExchangeRate);
                    AdvanceReceiptItems.Add(item);
                }

                else
                {
                    match.SetPercent(item.AdvanceReceiptPercent);
                    match.CalculateAmount(TotalAmountFr, ExchangeRate);

                }
            }
            //删除掉不存在的分录
            var itemIds = items.Select(item => item.Id).ToList();

            var deleted = AdvanceReceiptItems.Where(x => !itemIds.Contains(x.Id)).ToList();

            if (deleted.Any(x => x.AdvanceCollectId.HasValue))
                throw new UserFriendlyException("已经关联预收款信息不能删除", "100000");

            deleted.ForEach(x => AdvanceReceiptItems.Remove(x));

            if (AdvanceReceiptItems.Sum(x => x.AdvanceReceiptPercent) > 100)
                throw new UserFriendlyException("预收比例不能大于100%", "100000");

            if (AdvanceReceiptItems.Sum(x => x.AdvanceReceiptAmountFr) > TotalAmountFr)
                throw new UserFriendlyException("预收金额不能大于订单金额", "100000");

            //重新排序
            int index = 0;
            AdvanceReceiptItems.ToList().ForEach(x => x.SetIndex(index++));
        }

        #region

        protected override void AddOrUpdateItem(SaleOrderItem item)
        {
            if (Status == DocumentStatusType.Approved)
                throw new UserFriendlyException("审核单据不允许修改", "100000");

            if (!item.Product.Saleable)
                throw new UserFriendlyException($"产品：{item.Product.Code}-{item.Product.Name}不允许销售", "100000");

            if (Type == SaleOrderType.Standard && item.Product.Type != (int)ProductType.Stock)
                throw new UserFriendlyException($"标准销售只能选择库存类产品", "100000");

            var match = Items.FirstOrDefault(x => x.Id == item.Id);

            if (match == null)
            {
                match = item;

                match.CalculateBaiscUnitQuantity();
                match.CalculateAmount(IncludeTax, ExchangeRate, item.IsGift);
                
                Items.Add(match);
            }

            else
            {
                match.Change(item.Product, item.AuxiliaryUnit, item.ProductAuxiliaryUnit, item.AuxiliaryQuantity, item.Price, item.TaxRate,
                    item.IsGift, item.Remark);

                item.CalculateBaiscUnitQuantity();
                item.CalculateAmount(IncludeTax, ExchangeRate , item.IsGift);
                
            }
        }

        #endregion
    }

    public class SaleOrderItem : DocumentEntity
    {
        public bool IsGift {  get; private set; }

        private SaleOrderItem() { }

        public SaleOrderItem(Guid id, Product product, Unit saleUnit, ProductAuxiliaryUnit productAuxiliaryUnit, decimal saleQuantity, decimal price, TaxRate taxRate, bool isGift, string remark) :
            base(id, product, saleUnit, productAuxiliaryUnit, saleQuantity, price, taxRate, remark)
        {
            IsGift = isGift;
        }

        public void Change(Product product, Unit saleUnit, ProductAuxiliaryUnit productAuxiliaryUnit, decimal saleQuantity, decimal price, TaxRate taxRate, bool isGift, string remark)
        {
            base.Change(product, saleUnit, productAuxiliaryUnit, saleQuantity, price, taxRate, remark);

            SetIsGift(isGift);

            Validate();
        }

        #region
        private void SetIsGift(bool isGift)
        {
            IsGift = isGift;

            if (isGift)
            {
                Price = 0;
                TaxRate = null;
                TaxRateId = null;
                TaxRateValue = null;
            }
        }

        protected override void Validate()
        {
            base.Validate();

            if (AuxiliaryUnit == null)
                throw new UserFriendlyException("销售单位不存在", "100000");

            if (AuxiliaryQuantity <= 0)
                throw new UserFriendlyException("销售数量必须大于0", "100000");

            if (!IsGift && Price <= 0)
                throw new UserFriendlyException("单价必须大于0");
        }
        #endregion
    }

    /// <summary>
    /// 销售预收款
    /// </summary>
    public class SaleOrderAdvanceReceiptItem : AuditedAggregateRoot<Guid>, IMultiTenant
    {
        public Guid? TenantId { get; private set; }

        public decimal AdvanceReceiptPercent { get; private set; }

        public decimal AdvanceReceiptAmountFr { get; private set; }

        public decimal AdvanceReceiptAmount { get; private set; }

        public DateTime? DueDate { get; set; }

        public Guid? AdvanceCollectId { get; private set; }

        public int Index { get; private set; }

        private SaleOrderAdvanceReceiptItem() { }

        public SaleOrderAdvanceReceiptItem(Guid id, decimal advanceReceiptPercent, decimal advanceReceiptAmountFr, decimal advanceReceiptAmount, DateTime? dueDate, Guid? advanceCollectId, int index)
        {
            Id = id;
            AdvanceReceiptPercent = advanceReceiptPercent;
            AdvanceReceiptAmountFr = advanceReceiptAmountFr;
            AdvanceReceiptAmount = advanceReceiptAmount;
            DueDate = dueDate;
            AdvanceCollectId = advanceCollectId;
            Index = index;

            Validate();
        }

        public void SetPercent(decimal percent)
        {
            AdvanceReceiptPercent = percent;
        }

        public void SetIndex(int index)
        {
            Index = index;
        }

        public void CalculateAmount(decimal orderAmountFr, decimal exchangeRate)
        {
            AdvanceReceiptAmountFr = (orderAmountFr * AdvanceReceiptPercent / 100).ToMoney();
            AdvanceReceiptAmount = (AdvanceReceiptAmountFr * exchangeRate).ToMoney();

            if (AdvanceReceiptAmountFr <= 0 || AdvanceReceiptAmount <= 0)
                throw new UserFriendlyException("预收金额必须大于0", "100000");
        }

        #region
        private void Validate()
        {
            if (AdvanceReceiptPercent <= 0)
                throw new UserFriendlyException("预付比例必须大于0", "100000");
        }
        #endregion
    }
}
